import { ElMessage } from 'element-plus'

import router from '@/router'

import { getToken, removeAll } from '@/utils/auth'

import { AxiosCancer } from './helper/axiosCancel'
import axios, {
  AxiosError,
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  InternalAxiosRequestConfig,
} from 'axios'

const resCode = {
  tokenFail: '55555',
}

const axiosCanceler = new AxiosCancer()

export interface CustomRequestConfig extends InternalAxiosRequestConfig {
  noTip?: boolean
  cancel?: boolean
}

const createService = () => {
  const service = axios.create()

  service.interceptors.request.use(
    (config: CustomRequestConfig) => {
      const token = getToken()
      if (token) {
        config.headers[import.meta.env.VITE_APP_BASE_TOKEN] = token
      }

      // 默认不取消
      config.cancel ??= false
      config.cancel && axiosCanceler.addPending(config)

      return config
    },
    (error: AxiosError) => Promise.reject(error)
  )

  // 响应拦截器
  service.interceptors.response.use(
    (response: AxiosResponse & { config: CustomRequestConfig }) => {
      const { code, data, msg, message } = response.data
      const { noTip } = response.config
      console.log('res', code, msg, response)
      const _message = msg || message

      axiosCanceler.removePending(response.config)

      // token失效
      if (code === resCode.tokenFail) {
        ElMessage.closeAll()
        setTimeout(() => {
          router.replace('/login')
        })
        return Promise.reject(_message)
      }

      if (code !== '200' && code != '204') {
        if (!noTip) {
          ElMessage({
            type: 'error',
            message: _message,
          })
          return Promise.reject(_message)
        }
      }

      return data
    },
    (error: AxiosError) => {
      console.log('e', error, error.message)
      if (error.response && error.response.status === 401) {
        removeAll()
        location.reload()
        return Promise.reject(error)
      }
      if (error.response && error.response.status === 403) {
        // removeAll()
        // location.reload()
        return Promise.reject(error)
      }
      // 超时
      if (error.message.indexOf('timeout') > -1) {
        ElMessage({
          type: 'error',
          message: '请求超时',
        })
        return Promise.reject(error)
      }
      ElMessage({
        type: 'error',
        message: error.message,
      })
      return Promise.reject(error)
    }
  )

  return service
}

const createRequest = (service: AxiosInstance) => {
  return function <T>(config: AxiosRequestConfig): Promise<T> {
    const configDefault = {
      timeout: 10000,
      baseURL: import.meta.env.VITE_BASE_API,
      // data: {},
    }

    return service(Object.assign(configDefault, config))
  }
}

export const service = createService()

export const request = createRequest(service)<any>
